package com.fitapp;

import android.graphics.Color;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public class SportActivity extends Activity implements SensorEventListener
{
	// Sensor varialbes
	private SensorManager manager;
	private Sensor accelerator;
	private Sensor rotation;
	private DatabaseHelper helper = new DatabaseHelper( this );
	private long lastUpdate;
	private int trackCount = 0; // movement counter
	private boolean started = false;
	private int sizeUp = 0;

	int negCount = 0;
	int posCount = 0;
	float posAcc = 0;
	float negAcc = 0;

	private int sampleCounter = 0;
	private final int TOTAL_SAMPLES = 5;
	private double time;
	private double accels[] = new double[ TOTAL_SAMPLES ];
	private double currentRotation;
	private boolean rotChanged = false;
	private boolean accChanged = false;

	// Gui variables
	private Button btnStart;
	private Button btnStop;
	private TextView tvAmount;
	private TextView tvCountWatch;

	// Mulitimedia variables
	private MediaPlayer mPlayer;

	// Datamodel variables
	private int intendedAmount;
	private int reachedAmount;
	private int exerciseAmount;
	private long startTime;

	@Override
	public void onCreate( Bundle savedInstanceState )
	{
		super.onCreate( savedInstanceState );
		setContentView( R.layout.activity_sport ); // Connect gui

		// Get gui control elements
		btnStart = (Button) findViewById( R.id.btnStartSport );
		btnStop = (Button) findViewById( R.id.btnStopSport );
		btnStart.setTextColor( Color.GREEN );
		btnStop.setTextColor( Color.GRAY );
		btnStart.setEnabled( true );
		btnStop.setEnabled( false );
		tvAmount = (TextView) findViewById( R.id.tvAmount );
		tvCountWatch = (TextView) findViewById( R.id.tvCountWatch );
		tvCountWatch.setText( "0" );
		sizeUp = 0;

		// Init sensor
		manager = (SensorManager) getSystemService( SENSOR_SERVICE );
		accelerator = manager.getDefaultSensor( Sensor.TYPE_LINEAR_ACCELERATION );
		rotation = manager.getDefaultSensor( Sensor.TYPE_ROTATION_VECTOR );
	}

	protected void onResume()
	{
		super.onResume( );
		manager.registerListener( this, accelerator, SensorManager.SENSOR_DELAY_GAME );
		manager.registerListener( this, rotation, SensorManager.SENSOR_DELAY_GAME );

		// Get data from database
		DatabaseHelper helper = new DatabaseHelper( this );
		SQLiteDatabase db = helper.getReadableDatabase( );
		Cursor cursor = db.rawQuery( "SELECT * FROM Goals WHERE Type=? LIMIT 1", new String[ ] { DatabaseHelper.TYPE_BENDING } );
		if( cursor.getCount( ) == 1 )
		{
			cursor.moveToFirst( );
			reachedAmount = Integer.parseInt( cursor.getString( 3 ) );
			intendedAmount = Integer.parseInt( cursor.getString( 4 ) );
			cursor.close( );
		}

		if( reachedAmount == intendedAmount )
		{
			// Did enough exercises
			btnStart.setEnabled( false );
			Toast.makeText( this, "You already did enough knee banding for this month", Toast.LENGTH_SHORT ).show( );
		}
		else
		{
			// Regular exercise amount
			exerciseAmount = intendedAmount / 20;
			tvAmount.setText( "" + exerciseAmount );
		}
	}

	public void onPause()
	{
		super.onPause( );
		if( mPlayer != null )
		{
			mPlayer.release( );
		}
	}

	public void onBackPressed()
	{
		super.onBackPressed( );

		// Unregister sensor listener to save battery
		manager.unregisterListener( this );
	}

	@Override
	public void onAccuracyChanged( Sensor arg0, int arg1 )
	{

	}

	private double getAvg( double[ ] a )
	{
		double total = 0;

		for( int i = 0; i < a.length; i++ )
		{
			total = total + Math.abs( a[ i ] );
		}

		return ( total / a.length );
	}

	@Override
	public void onSensorChanged( SensorEvent event )
	{
		Sensor sensor = event.sensor;
		// User pressed start button
		if( started )
		{
			double a = System.currentTimeMillis( );
			// Get data from rotation sensor
			if( sensor.getType( ) == Sensor.TYPE_ROTATION_VECTOR )
			{
				// Compare two values with 1s interval
				if( a - lastUpdate > 1000 )
				{
					// System.out.println( event.values[ 0 ] + ":" +
					// currentRotation );
					// rotation has to be big enough
					if( Math.abs( event.values[ 0 ] ) - currentRotation > 0.3 )
					{
						System.out.println( "ROT" );
						rotChanged = true;
					}
					currentRotation = Math.abs( event.values[ 0 ] );
					lastUpdate = System.currentTimeMillis( );
				}

			}
			// Get data from acceleration sensor
			if( sensor.getType( ) == Sensor.TYPE_LINEAR_ACCELERATION )
			{
				double currentTime = System.currentTimeMillis( );
				// take specific number of values from sensor
				if( sampleCounter < TOTAL_SAMPLES - 1 )
				{
					if( sampleCounter == 0 )
					{
						time = currentTime;
					}

					accels[ sampleCounter ] = event.values[ 0 ];
					sampleCounter++;
				}
				// all values are collected, start analyzing
				else if( sampleCounter == ( TOTAL_SAMPLES - 1 ) )
				{
					accels[ sampleCounter ] = event.values[ 0 ];
					double avgAccel = getAvg( accels );
					double timeDelta = ( ( currentTime - time ) / 1000 );
					// System.out.println("AVG: "+avgAccel);
					if( avgAccel > 0.45 || avgAccel < -0.45 )
					{
						// move has to be long enough
						if( timeDelta > 0.2 )
						{
							accChanged = true;
						}
						sampleCounter = 0;

					}

				}
			}
		}

		// both sensors detected bending move
		if( rotChanged && accChanged )
		{
			trackCount++;
			sizeUp += 40;

			if( trackCount + reachedAmount < intendedAmount )
			{
				if( trackCount == exerciseAmount )
				{
					mPlayer = MediaPlayer.create( this, R.raw.one_more );
					mPlayer.start( );
				}
				else if( trackCount > exerciseAmount )
				{
					mPlayer = MediaPlayer.create( this, R.raw.nice_one );
					mPlayer.start( );
					onBtnStopSportClicked( null );
				}
			}
			else
			{
				mPlayer = MediaPlayer.create( this, R.raw.nice_one );
				mPlayer.start( );
				onBtnStopSportClicked( null );
			}

			tvCountWatch.setText( "" + trackCount );
			// Grow numbers to motivate
			tvCountWatch.setTextSize( 20 + ( sizeUp % 200 ) );

			rotChanged = false;
			accChanged = false;
		}
	}

	public void onBtnStartSportClicked( View view )
	{
		// Update gui
		btnStart.setTextColor( Color.GRAY );
		btnStop.setTextColor( Color.GREEN );
		btnStart.setEnabled( false );
		btnStop.setEnabled( true );
		startTime = ( System.currentTimeMillis( ) / 1000L );
		tvCountWatch.setText( "0" );
		sizeUp = 0;
		trackCount = 0;
		started = true;

		Toast toast = Toast.makeText( SportActivity.this, "Ok, start now!", Toast.LENGTH_SHORT );
		toast.show( );
	}

	public void onBtnStopSportClicked( View view )
	{
		// Update gui
		btnStart.setTextColor( Color.GRAY );
		btnStop.setTextColor( Color.GRAY );
		btnStart.setEnabled( false );
		btnStop.setEnabled( false );

		// Unregister sensor listener to save battery
		manager.unregisterListener( this );

		// Save workout in database
		started = false;
		SQLiteDatabase db = helper.getWritableDatabase( );
		ContentValues values = new ContentValues( );
		int unixTime = (int) ( System.currentTimeMillis( ) / 1000L );
		values.put( "Type", DatabaseHelper.TYPE_BENDING );
		values.put( "Count", trackCount );
		values.put( "Date", unixTime );
		values.put( "Time", startTime );
		db.insert( "Activities", null, values );

		// Save progress in database
		db = helper.getWritableDatabase( );
		values = new ContentValues( );
		values.put( "Reached", trackCount + reachedAmount );
		db.update( "Goals", values, "Type=?", new String[ ] { DatabaseHelper.TYPE_BENDING } );

		Toast toast = Toast.makeText( SportActivity.this, "Activity saved", Toast.LENGTH_SHORT );
		toast.show( );

		db.close( );
		helper.close( );
		// Stop Counter
	}

}
